package com.example.vehicle.Controller;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.example.vehicle.Entity.ChargingStation;
import com.example.vehicle.HelloApplication;
import com.example.vehicle.Utils.HttpClientUtil;
import com.example.vehicle.Utils.PageUtil;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;

import java.io.IOException;
import java.net.URL;
import java.util.*;

/**
 * @name: MainViewController
 * @description: 主界面控制器类。
 * @author: Lulu Zhao
 **/
public class MainViewController implements Initializable {
    @FXML
    public TableView<ChargingStation> chargingStationTable;

    @FXML
    public TableColumn<ChargingStation, String> columnChargingStationID;

    @FXML
    public TableColumn<ChargingStation, String> columnLocation;

    @FXML
    public TableColumn<ChargingStation, String> columnBrand;

    @FXML
    public TableColumn<ChargingStation, String> columnProvider;

    @FXML
    public TableColumn<ChargingStation, String> columnState;

    @FXML
    public Pagination chargingStationPagination;

    @FXML
    public MenuItem profileID;

    @FXML
    public MenuItem profileCurrentHashTime;

    @FXML
    public MenuItem profileQuit;

    @FXML
    public MenuItem stationQuery;

    @FXML
    public MenuItem stationBook;

    @FXML
    public MenuItem routePlan;

    @FXML
    public ChoiceBox<String> choiceStation;

    @FXML
    public DatePicker datePicker;

    @FXML
    public TextArea resultText;

    @FXML
    public DialogPane routePlanDialogPane;

    /**
     * @name: initialize
     * @description: 界面初始化。
     * @params: [url, resourceBundle]
     * @return: void
     * @author: Lulu Zhao
     */
    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        profileID.setText("ID：" + HelloApplication.loginUser.getClientID());
        profileCurrentHashTime.setText("动态口令有效期：" + HelloApplication.loginUser.getCurrentHashTimes());
        List<ChargingStation> chargingStationList = getTrueTableData();
        if (chargingStationList == null) {
            return;
        }
        tableConfig(chargingStationList);
        for (ChargingStation chargingStation : chargingStationList) {
            choiceStation.getItems().add(String.valueOf(chargingStation.getChargingStationID()));
        }
    }

    /**
     * @name: tableConfig
     * @description: 表格列属性配置。
     * @params: [chargingStationList]
     * @return: void
     * @author: Lulu Zhao
     */
    private void tableConfig(List<ChargingStation> chargingStationList) {
        columnChargingStationID.setCellValueFactory(new PropertyValueFactory<>("ChargingStationID"));
        columnLocation.setCellValueFactory(new PropertyValueFactory<>("Location"));
        columnBrand.setCellValueFactory(new PropertyValueFactory<>("Brand"));
        columnProvider.setCellValueFactory(new PropertyValueFactory<>("Provider"));
        columnState.setCellValueFactory(new PropertyValueFactory<>("State"));
        chargingStationTable.setItems(FXCollections.observableList(chargingStationList));
        PageUtil<ChargingStation> pageUtil = new PageUtil<>(chargingStationList, 10);
        chargingStationPagination.pageCountProperty().bindBidirectional(pageUtil.getTotalPage());
        chargingStationPagination.setPageFactory(pageIndex -> {
            chargingStationTable.setItems(FXCollections.observableList(pageUtil.getCurrentPageDataList(pageIndex)));
            return chargingStationTable;
        });
    }

    /**
     * @name: onTableTestButtonClick
     * @description: 表格测试按钮回调函数。
     * @params: []
     * @return: void
     * @author: Lulu Zhao
     */
    @FXML
    protected void onTableTestButtonClick() {
        List<ChargingStation> chargingStationList = getTableData();
        tableConfig(chargingStationList);
    }

    /**
     * @name: getTableData
     * @description: 返回表格测试模拟数据。
     * @params: []
     * @return: java.util.List<com.example.vehicle.Entity.ChargingStation>
     * @author: Lulu Zhao
     */
    private List<ChargingStation> getTableData() {
        return Arrays.asList(
                new ChargingStation("0001", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0002", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0003", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0004", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0005", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0006", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0007", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0008", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0009", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0010", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0011", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0012", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0013", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0014", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0015", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0016", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0017", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0018", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0019", "1,1", "Huawei", "Huawei(Beijing)", "free"),
                new ChargingStation("0020", "1,1", "Huawei", "Huawei(Beijing)", "free"));
    }

    /**
     * @name: onTrueTableTestButtonClick
     * @description: 真实数据表格测试按钮回调函数。
     * @params: []
     * @return: void
     * @author: Lulu Zhao
     */
    @FXML
    protected void onTrueTableTestButtonClick() {
        List<ChargingStation> chargingStationList = getTrueTableData();
        if (chargingStationList == null) {
            return;
        }
        tableConfig(chargingStationList);
    }

    /**
     * @name: getTrueTableData
     * @description: 返回表格测试真实数据。
     * @params: []
     * @return: java.util.List<com.example.vehicle.Entity.ChargingStation>
     * @author: Lulu Zhao
     */
    private List<ChargingStation> getTrueTableData() {
        String response = HttpClientUtil.doGet("http://localhost:8080/chacc/chargingstations");
        JSONObject responseJson = JSONUtil.parseObj(response);
        String payload = responseJson.get("payload").toString();
        if (payload.equals("")) {
            return null;
        }
        payload = payload.substring(1, payload.length() - 1);
        String[] payloads = payload.split(",\\{");
        for (int i = 1; i < payloads.length; i++) {
            payloads[i] = "{" + payloads[i];
        }
        ChargingStation[] result = new ChargingStation[payloads.length];
        for (int i = 0; i < payloads.length; i++) {
            result[i] = new ChargingStation();
            JSONObject keyAndRecord = JSONUtil.parseObj(payloads[i]);
            String Record = keyAndRecord.get("Record").toString();
            JSONObject record = JSONUtil.parseObj(Record);
            result[i].setChargingStationID(record.get("ChargingStationID").toString());
            result[i].setLocation(record.get("Location").toString());
            result[i].setBrand(record.get("Brand").toString());
            result[i].setProvider(record.get("Provider").toString());
            result[i].setState(record.get("State").toString());
        }
        return Arrays.asList(result);
    }

    /**
     * @name: onRefreshButtonCilck
     * @description: 刷新充电桩情况按钮回调函数。
     * @params: []
     * @return: void
     * @author: Lulu Zhao
     */
    @FXML
    protected void onRefreshButtonClick() {
        List<ChargingStation> chargingStationList = getTrueTableData();
        if (chargingStationList == null) {
            return;
        }
        tableConfig(chargingStationList);
    }

    /**
     * @name: onCommitBookButtonClick
     * @description: 提交充电预约按钮回调函数。
     * @params: []
     * @return: void
     * @author: Lulu Zhao
     */
    @FXML
    protected void onCommitBookButtonClick() {
        resultText.clear();
        if (choiceStation.getValue() == null) {
            resultText.setText("充电预约提交失败！\n" +
                    "失败原因：请选择想要预约使用的充电桩。");
        } else if (datePicker.getValue() == null) {
            resultText.setText("充电预约提交失败！\n" +
                    "失败原因：请填写预约使用时间。");
        } else {
            Map<String, String> param = new HashMap<>();
            param.put("chargingStationId", choiceStation.getValue());
            String response = HttpClientUtil.doGet("http://localhost:8080/chacc/queryChargingStationById", param);
            JSONObject responseJson = JSONUtil.parseObj(response);
            String payload = responseJson.get("payload").toString();
            JSONObject payloadJson = JSONUtil.parseObj(payload);
            if (!payloadJson.get("State").toString().equals("free")) {
                resultText.setText("充电预约提交失败！\n" +
                        "失败原因：此充电桩暂不可用。");
            } else {
                param.put("chargingStationID", choiceStation.getValue());
                param.put("location", payloadJson.get("Location").toString());
                param.put("brand", payloadJson.get("Brand").toString());
                param.put("provider", payloadJson.get("Provider").toString());
                param.put("state", "booked");
                String responseUpdate = HttpClientUtil.doPost("http://localhost:8080/chacc/update", param);
                JSONObject responseUpdateJson = JSONUtil.parseObj(responseUpdate);
                if (responseUpdateJson.get("status").toString().equals("ok")) {
                    String[] dates = datePicker.getValue().toString().split("-");
                    resultText.setText("充电预约提交成功！\n" +
                            "预约信息如下：\n" +
                            "充电桩：" + param.get("chargingStationID") + "\n" +
                            "预约时间：" + dates[0] + "年" + dates[1] + "月" + dates[2] + "日\n");
                }
            }
        }
    }

    /**
     * @name: onCancelBookButtonClick
     * @description: 取消充电预约按钮回调函数。
     * @params: []
     * @return: void
     * @author: Lulu Zhao
     */
    @FXML
    protected void onCancelBookButtonClick() {
        resultText.clear();
        if (choiceStation.getValue() == null) {
            resultText.setText("取消充电预约失败！\n" +
                    "失败原因：请选择取消预约使用的充电桩。");
        } else {
            Map<String, String> param = new HashMap<>();
            param.put("chargingStationId", choiceStation.getValue());
            String response = HttpClientUtil.doGet("http://localhost:8080/chacc/queryChargingStationById", param);
            JSONObject responseJson = JSONUtil.parseObj(response);
            String payload = responseJson.get("payload").toString();
            JSONObject payloadJson = JSONUtil.parseObj(payload);
            if (payloadJson.get("State").toString().equals("free")) {
                resultText.setText("取消充电预约失败！\n" +
                        "失败原因：此充电桩无人使用或预约。");
            } else {
                param.put("chargingStationID", choiceStation.getValue());
                param.put("location", payloadJson.get("Location").toString());
                param.put("brand", payloadJson.get("Brand").toString());
                param.put("provider", payloadJson.get("Provider").toString());
                param.put("state", "free");
                String responseUpdate = HttpClientUtil.doPost("http://localhost:8080/chacc/update", param);
                JSONObject responseUpdateJson = JSONUtil.parseObj(responseUpdate);
                if (responseUpdateJson.get("status").toString().equals("ok")) {
                    resultText.setText("取消充电预约成功！");
                }
            }
        }
    }

    @FXML
    protected void onRoutePlanButtonClick() throws IOException {
        Stage popStage = new Stage();
        FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("route-view.fxml"));
        Scene scene = new Scene(fxmlLoader.load());
        popStage.setResizable(false);
        popStage.setTitle("路径规划方案");
        popStage.setScene(scene);
        popStage.show();
    }

    /**
     * @name: menuQuit
     * @description: 菜单栏退出系统功能。
     * @params: []
     * @return: void
     * @author: Lulu Zhao
     */
    @FXML
    protected void menuQuit() throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
        Scene scene = new Scene(fxmlLoader.load());
        HelloApplication.stage.setScene(scene);
    }

    /**
     * @name: menuAbout
     * @description: 菜单栏关于功能。
     * @params: []
     * @return: void
     * @author: Lulu Zhao
     */
    @FXML
    protected void menuAbout() {
        Alert alert = new Alert(Alert.AlertType.NONE);
        alert.setContentText("你说的对，但是《基于区块链的车辆网数据共享平台》是由北京交通大学计算机学院某毕业生自主研发的一款全新开放世界车辆信息共享平台。" +
                "数据共享发生在一个被称作「上园村3号」的幻想世界。在这里，被TA授权的车辆将被分发「哈希链」，用于身份验证。" +
                "你将扮演一位名为「旅行者」的神秘角色，在自由的自驾旅途中邂逅性格各异、能力独特的同行者们，和他们一起争夺充电桩——同时，逐步发掘「百胶带」的真相。");
        alert.getDialogPane().getButtonTypes().add(ButtonType.OK);
        alert.showAndWait();
    }
}
